package com.caiyi.financial.nirvana.sms.gateway.sgip;


import com.caiyi.financial.nirvana.sms.gateway.sgip.handler.SGIPControlHandler;
import com.caiyi.financial.nirvana.sms.gateway.sgip.handler.SGIPReceiverHandler;
import com.caiyi.financial.nirvana.sms.gateway.sgip.message.SGIPMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufHolder;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.traffic.ChannelTrafficShapingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

public class SGIPClientInitializer extends ChannelInitializer<SocketChannel> {

    private static final Logger logger = LoggerFactory.getLogger(SGIPClientInitializer.class);

    // 客户端
    private SGIPClient client;

    // 构造
    public SGIPClientInitializer(SGIPClient client) {
        this.client = client;
    }

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {

        ChannelPipeline pipeline = channel.pipeline();

        // 长度解码器
        pipeline.addLast("length field decoder", new LengthFieldBasedFrameDecoder(1024, 0, 4, -4, 0));

        // 解码器
        pipeline.addLast("decoder", new SGIPStreamDecoder());

        // 编码器
        pipeline.addLast("encoder", new SGIPStreamEncoder());

        // 增加流量整形 ，每个连接每秒发送，接收消息数不超过配置的值
        long traffic = client.info.getFlowSpeed();
        logger.debug("{} TrafficShaping: flowSize={}", client.info.getAccessNumber(), traffic);
        // 这个放在前边，保证真实发送到连接上的速率。可以避免网关抖动造成的发送超速。
        // 网关抖动时，网关会先积压大量response，然后突然发送大量response给SessionManager,
        // 造成在Session里等待的消息集中发送。
        pipeline.addLast("CMPPChannelTrafficBefore", new SGIPChannelTrafficShapingHandler(traffic, 0, 250));

        // 这个放在后边，限制发送方的速度，超速后设置连接不可写
        pipeline.addLast("CMPPChannelTrafficAfter", new SGIPChannelTrafficShapingHandler(traffic, 0, 250));

        // 空闲事件将发送UP事件
        pipeline.addLast("idleCheck", new IdleStateHandler(client.idleNotifyTime * 2, 0,
                0, TimeUnit.SECONDS));

        // 接收控制器
        pipeline.addLast("receiver handler", new SGIPReceiverHandler(client));

        // 总控制器
        pipeline.addLast("controler", new SGIPControlHandler(client));
    }

    /**
     * 重写了calculateSize方法，按消息条数计算流量
     **/
    private class SGIPChannelTrafficShapingHandler extends ChannelTrafficShapingHandler {

        public SGIPChannelTrafficShapingHandler(long writeLimit, long readLimit, long checkInterval) {
            super(writeLimit, readLimit, checkInterval);
            setMaxWriteSize(75);
            setMaxWriteDelay(2500);
        }

        private boolean isRequestMsg(SGIPMessage msg) {
            long commandId = msg.getCommandID();
            return (commandId & 0x80000000L) == 0L;
        }

        @Override
        protected long calculateSize(Object msg) {
            if (msg instanceof ByteBuf) {
                return ((ByteBuf) msg).readableBytes();
            }
            if (msg instanceof ByteBufHolder) {
                return ((ByteBufHolder) msg).content().readableBytes();
            }
            if (msg instanceof SGIPMessage) {
                // 只计算Request信息
                if (isRequestMsg((SGIPMessage) msg)) {
                    return 1;
                }
            }
            return -1;
        }
    }
}
